﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NH.Elateral.PipeManagement.Core.Interfaces;

namespace NH.Elateral.PipeManagement.Core
{
	public class PipeManager
	{
		private const string PIPE_COMMAND_PREFIX = "Pipes.";

		private readonly IPipeStatusFormatter _statusFormatter;
		private readonly IPipeRepository _pipeRepository;
		private readonly ICommandParser _commandParser;

		private IQueryable<Pipe> _pipes;

		#region _ctor
		public PipeManager(IPipeRepository pipeRepository, IPipeStatusFormatter statusFormatter) :
			this(pipeRepository, statusFormatter, null)
		{
			//this is to get the first 2 test passing
		}

		public PipeManager(IPipeRepository pipeRepository, 
				IPipeStatusFormatter statusFormatter, 
			ICommandParser commandParser)
		{
			this._pipeRepository = pipeRepository;
			this._statusFormatter = statusFormatter;
			this._commandParser = commandParser;

			_pipes = new List<Pipe>(_pipeRepository.GetAllPipes()).AsQueryable();
		} 
		#endregion
		
		public string GetPipeStatus()
		{
			StringBuilder sb = new StringBuilder();
			_pipes.ToList()
				.ForEach(pipe => {
					sb.Append(_statusFormatter.Format(pipe));
					sb.Append(",");
				});
			//remove last comma
			return sb.Length > 1 ? sb.ToString().Substring(0, sb.Length-1) : sb.ToString();
		}

		public string ActOn(string command)
		{
			string commandWithOutIntialPrefix = command.Replace(PIPE_COMMAND_PREFIX, "");
			string[] commandSeparators = new String[] { "," };
			string[] commands = commandWithOutIntialPrefix.Split(commandSeparators, StringSplitOptions.RemoveEmptyEntries);

			foreach (string cmd in commands)
			{
				ParseCommand parsedCmd = _commandParser.Parse(cmd);
				Pipe pipe = _pipes.WherePipeHaveId(parsedCmd.PipeID);
				if (pipe != null)
				{
					pipe.IsOpen = parsedCmd.PipeState;
				}
			}
			return GetPipeStatus();
		}
	}

	public static class QueryableExtensions
	{
		public static Pipe WherePipeHaveId(this IQueryable<Pipe> source, int pipeId)
		{
			return (from p in source
					where p.PipeId.Equals(pipeId)
					select p).SingleOrDefault();
		}
	}
}
